
#include<iostream>
#include"func.h"
#include<opencv2/imgcodecs.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc.hpp>
#include<opencv2/objdetect.hpp>
#include<opencv2/opencv.hpp>
#include<opencv2/ximgproc.hpp>
#include<string>
#include<vector>
#include<fstream>


using namespace std;
using namespace cv;

void tuxiangjuanji()
{
    uchar points[25]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25};
    Mat img(5,5,CV_8UC1,points);

    Mat  kernel=(Mat_<float>(3,3)<<1,2,1,2,0,2,1,2,1);//卷积模板
    Mat kernel_norm=kernel/12;//卷积模板归一化
    Mat result,result_norm;
    filter2D(img,result,CV_32F,kernel,Point(-1,-1),2,BORDER_CONSTANT);//图像卷积函数(输入图，输出图，输出图类型，卷积模板，基准点，偏值，像素外推标志)
    filter2D(img,result_norm,CV_32F,kernel_norm,Point(-1,-1),2,BORDER_CONSTANT);
    cout<<"result:"<<endl<<result<<endl;
    cout<<"result_norm:"<<endl<<result_norm<<endl;

    Mat test=imread("/home/zhanjiabin/桌面/task/study/test.jpg");
    Mat test_filter;
    filter2D(test,test_filter,-1,kernel_norm,Point(-1,-1),2,BORDER_CONSTANT);
    imshow("test",test);
    imshow("test_filter",test_filter);
    waitKey(0);
}

void xianxinglvbo()//适用高斯噪声
{
    VideoCapture cap(0);

    //均值滤波变量
    Mat result_3,result_9;
    Mat img;

    //方框滤波变量
    Mat resultNorm,result;

    //高斯滤波变量
    Mat result_5G,result_9G;

    while(1)
    {
        cap.read(img);

        //均值滤波
        blur(img,result_3,Size(3,3));//均值滤波函数(输入图，输出图，滤波器尺寸)
        blur(img,result_9,Size(9,9));

        //方框滤波
        //归一化
        boxFilter(img,resultNorm,-1,Size(3,3),Point(-1,-1),true);
        //不归一化
        boxFilter(img,result,-1,Size(3,3),Point(-1,-1),false);//方框滤波函数(输入图，输出图，输出图数据类型<-1时自动选择>,卷积核尺寸，卷积核基准点，是否归一化卷积核标志)

        //高斯滤波
        GaussianBlur(img,result_5G,Size(5,5),10,20);//高斯滤波函数(输入图，输出图，卷积核尺寸，x方向标准偏差，y方向标准偏差<xy均为0则根据滤波器尺寸计算>）
        GaussianBlur(img,result_9G,Size(9,9),10,20);

        imshow("3*3均值滤波",result_3);
        imshow("9*9均值滤波",result_9);
        imshow("归一化方框滤波",resultNorm);
        imshow("不归一化方框滤波",result);
        imshow("5*5高斯滤波",result_5G);
        imshow("9*9高斯滤波",result_9G);
        imshow("原图",img);
        waitKey(1);
    }
}

void feixianxinglvbo()//适用椒盐噪声
{
    VideoCapture cap(0);
    
    Mat result_3,result_9;
    Mat img;

    while(1)
    {
        cap.read(img);

        //中值滤波
        medianBlur(img,result_3,3);//中值滤波函数(输入图，输出图，滤波器尺寸)
        medianBlur(img,result_9,9);

        imshow("原图",img);
        imshow("滤波器尺寸为3",result_3);
        imshow("滤波器尺寸为9",result_9);

        waitKey(1);
    }

}

void bianyuanjiance()
{
    Mat imgt=imread("/home/zhanjiabin/桌面/task/study/test.jpg");
    Mat img;
    cvtColor(imgt,img,COLOR_BGR2GRAY);

    Mat resultx,resulty,resultxy;

    //Sobel算子边缘检测
    //x方向一阶边缘检测
    Sobel(img,resultx,CV_16S,1,0,1); //Sobel算子边缘检测函数(输入图，输出图，输出图数据类型，边缘检测阶数，缩放因子，Sobel算子尺寸<1对应3>)
    convertScaleAbs(resultx,resultx);//求绝对值函数(输入图，输出图)

    //y方向一阶边缘检测
    Sobel(img,resulty,CV_16S,0,1,3);
    convertScaleAbs(resulty,resulty);

    //全图一阶边缘检测
    resultxy=resultx+resulty;

    // imshow("x方向边缘检测",resultx);
    // imshow("y方向边缘检测",resulty);
    imshow("Sobel算子全图边缘检测",resultxy);


    //Scharr算子边缘检测
    //x方向边缘检测
    Mat resultX,resultY,resultXY;
    Scharr(img,resultX,CV_16S,1,0);//Scharr算子边缘检测函数(输入图，输出图，输出图数据类型，边缘检测阶数，缩放因子);
    convertScaleAbs(resultX,resultX);

    //y方向边缘检测
    Scharr(img,resultY,CV_16S,1,0);
    convertScaleAbs(resultY,resultY);

    //全图边缘检测
    resultXY=resultX+resultY;

    // imshow("resultX",resultX);
    // imshow("resultY",resultY);
    imshow("Scharr算子全图边缘检测",resultXY);

    // imshow("img",img);
    waitKey(0);
}

void bianyuanjiance2()
{
    Mat img=imread("/home/zhanjiabin/桌面/task/study/test.jpg");
    Mat result,resultg,resultG;


    //Laplacian算子边缘检测(配合高斯滤波使用)
    //未滤波
    Laplacian(img,result,CV_16S,3,1,0);//拉普拉斯算子边缘检测函数(输入图，输出图，输出图数据类型，边缘检测滤波器尺寸大小，缩放因子，偏值)
    convertScaleAbs(result,result);

    //滤波
    GaussianBlur(img,resultg,Size(3,3),5,0);
    Laplacian(resultg,resultG,CV_16S,3,1,0);
    convertScaleAbs(resultG,resultG);

    imshow("拉普拉斯未滤波",result);
    imshow("拉普拉斯滤波后",resultG);
    

    //canny算法边缘检测
    Mat resultHigh,resultLow,resultG2t,resultG2;

    //大阈值边缘检测
    Canny(img,resultHigh,100,200,3);//Canny算法边缘检测函数(输入图，输出图，第一个滞后阈值，第二个滞后阈值，Sobel算子直径)

    //小阈值边缘检测
    Canny(img,resultLow,20,40,3);

    //高斯滤波后Canny边缘检测
    GaussianBlur(img,resultG2t,Size(3,3),5);
    Canny(resultG2t,resultG2,100,200,3);

    
    imshow("canny算法大阈值边缘检测",resultHigh);
    imshow("canny算法小阈值边缘检测",resultLow);
    imshow("canny算法高斯滤波后边缘检测",resultG2);

    waitKey(0);
}

void liantongyufenxi()
{
    Mat img=imread("/home/zhanjiabin/桌面/task/study/t9.jpg");
    Mat rice,riceBW;

    cvtColor(img,rice,COLOR_BGR2GRAY);
    threshold(rice,riceBW,50,255,THRESH_BINARY);//小于50的部分为0，其余为255
    
    RNG rng(10086);//生成随机数
    Mat out;
    int number=connectedComponents(riceBW,out,8,CV_16U);//统计连通域个数函数(输入图，输出图，连通域邻域大小，输出图像数据类型)
    vector<Vec3b>colors;
    for(int i=0;i<number;i++)
    {
        //使用均匀分布的随机数确定标记的连通域的颜色
        Vec3b vec3=Vec3b(rng.uniform(0,255),rng.uniform(2,255),rng.uniform(0,255));
        colors.push_back(vec3);
    }

    //用不同颜色标记不同连通域
    Mat result=Mat::zeros(rice.size(),img.type());
    int w=result.cols;
    int h=result.rows;
    for(int row=0;row<h;row++)
    {
        for(int col=0;col<w;col++)
        {
            int label=out.at<uint16_t>(row,col);
            if(label=0)
            {
                continue;
            }
            result.at<Vec3b>(row,col)=colors[label];
        }
    }

    imshow("原图",img);
    imshow("标记后图像",result);




    waitKey(0);
}

void yanseshibie()
{
    Mat img;
    VideoCapture cap(0);
    Mat mask;

    Scalar upper(254,255,255);//多通道数据结构
    Scalar lower(54,180,233);

    while(1)
    {
        cap.read(img);//读取图像

        inRange(img,lower,upper,mask);//检测矩阵各通道值是否在范围内函数(输入图，最低值，最高值，输出图)
        // imshow("原图",img);
        imshow("橙色区域",mask);

        waitKey(1);
    }
}

void fushipengzhang()
{
    Mat src=(Mat_<uchar>(6,6)<<
                                0,  0,  0,  0,255,  0,
                                0,255,255,255,255,255,
                                0,255,255,255,255,  0,
                                0,255,255,255,255,  0,
                                0,255,255,255,255,  0,
                                0,  0,  0,  0,  0,  0);

    Mat st1 = getStructuringElement(0,Size(3,3));//结构元素生成函数(结构元素类型标志，结构元素尺寸)
    Mat st2 = getStructuringElement(1,Size(3,3));

    //腐蚀
    Mat es,es2;
    erode(src,es,st1);//腐蚀函数(原图，输出图，结构元素)
    erode(src,es2,st2);
    namedWindow("src",WINDOW_GUI_NORMAL);
    namedWindow("es",WINDOW_GUI_NORMAL);
    namedWindow("es2",WINDOW_GUI_NORMAL);
    imshow("src",src);
    imshow("es",es);
    imshow("es2",es2);

    //膨胀
    Mat ds1,ds2;
    dilate(src,ds1,st1);
    dilate(src,ds2,st2);
    namedWindow("ds",WINDOW_GUI_NORMAL);
    namedWindow("ds2",WINDOW_GUI_NORMAL);
    imshow("ds",ds1);
    imshow("ds2",ds2);

    waitKey(0);
}

void fushipengzhangyingy()
{
    Mat src=(Mat_<uchar>(10,10)<<
                                0,  0,  0,  0,255,  0,  0,  0,  0,  0,
                                0,255,255,255,255,255,255,  0,  0,  0,
                                0,255,255,255,255,  0,255,255,255,  0,
                                0,255,255,255,255,  0,255,  0,  0,255,
                                0,255,255,255,255,  0,255,255,255,255,
                                0,  0,  0,  0,  0,  0,  0,255,255,255,
                                0,255,255,255,255,  0,255,  0,  0,255,
                                0,255,255,255,255,  0,255,255,255,255,
                                0,255,255,255,255,255,255,  0,  0,  0,
                                0,255,255,255,255,  0,255,  0,  0,255
                                );

    namedWindow("src",WINDOW_NORMAL);
    imshow("src",src);

    Mat st = getStructuringElement(0,Size(3,3));//生成结构元素
    namedWindow("st",WINDOW_NORMAL);
    imshow("st",st);

    Mat open,close,tidu,dingmao,heimao,jizhongjibuzhong;

    //开运算
    morphologyEx(src,open,MORPH_OPEN,st);//形态学操作函数(原图，输出图，操作类型，结构元素)
    namedWindow("open",WINDOW_NORMAL);
    imshow("open",open);

    //闭运算
    morphologyEx(src,close,MORPH_CLOSE,st);//形态学操作函数(原图，输出图，操作类型，结构元素)
    namedWindow("close",WINDOW_NORMAL);
    imshow("close",close);

    //形态学梯度运算
    morphologyEx(src,tidu,MORPH_GRADIENT,st);//形态学操作函数(原图，输出图，操作类型，结构元素)
    namedWindow("tidu",WINDOW_NORMAL);
    imshow("tidu",tidu);

    //顶帽运算
    morphologyEx(src,dingmao,MORPH_TOPHAT,st);//形态学操作函数(原图，输出图，操作类型，结构元素)
    namedWindow("dingmao",WINDOW_NORMAL);
    imshow("dingmao",dingmao);

    //黑帽运算
    morphologyEx(src,heimao,MORPH_BLACKHAT,st);//形态学操作函数(原图，输出图，操作类型，结构元素)
    namedWindow("heimao",WINDOW_NORMAL);
    imshow("heimao",heimao);

    //击中击不中变换
    morphologyEx(src,jizhongjibuzhong,MORPH_HITMISS,st);//形态学操作函数(原图，输出图，操作类型，结构元素)
    namedWindow("jizhongjibuzhong",WINDOW_NORMAL);
    imshow("jizhongjibuzhong",jizhongjibuzhong);

    waitKey(0);
}

// void tuxiangxihua()//版本冲突，编译错误
// {
//     Mat img=imread("/home/zhanjiabin/桌面/task/study/white.jpg",IMREAD_ANYCOLOR);

//     Mat words=Mat::zeros(100,200,CV_8UC1);
//     putText(words,"learn",Point(30,30),2,1,Scalar(255),2);
//     putText(words,"opencv 4",Point(30,60),2,1,Scalar(255),2);
//     circle(words,Point(80,75),10,Scalar(255),-1);
//     circle(words,Point(130,75),10,Scalar(255),3);

//     //图像细化
//     Mat th1,th2;
//     ximgproc::thinning(img,img,0);//图像细化函数(原图，输出图，细化算法标志)
//     ximgproc::thinning(words,th2,0);

//     imshow("th1",th1);
//     imshow("img",img);
//     namedWindow("th2",WINDOW_NORMAL);
//     imshow("th2",th2);
//     namedWindow("words",WINDOW_NORMAL);
//     imshow("words",words);

//     waitKey(0);

// }

void lunkuojiance()
{
    Mat img;
    VideoCapture cap(0);
    Mat mask;
    int t,i;

    Mat gray,binary;//存放灰度和二值化图像
    vector<vector<Point>> contours;//存放找到的轮廓
    vector<Vec4i> hie;//存放轮廓结构变量
    

    while(1)
    {
        //获取图像
        cap.read(img);

        //图像预处理
        cvtColor(img,gray,COLOR_BGR2GRAY);//将图像转为灰度图
        GaussianBlur(gray,gray,Size(13,13),4,4);//高斯滤波
        threshold(gray,binary,170,255,THRESH_BINARY | THRESH_OTSU);//自适应二值化

        //寻找轮廓
        findContours(binary,contours,hie,RETR_TREE,CHAIN_APPROX_SIMPLE,Point());//寻找轮廓函数(输入图，存放轮廓的容器，存放轮廓结构容器，轮廓检测方法，轮廓逼近方法，可选的轮廓偏移参数)
        //绘制轮廓
        
        for(t=0;t<contours.size();t++)
        {
            drawContours(img,contours,t,Scalar(0,0,255),2,8);//画轮廓函数(目标图，轮廓容器，绘制轮廓数，颜色，线粗，边界线连接类型)
        }
        for(i=0;i<hie.size();i++)
        {
            cout<<hie[i]<<endl;
        }

        imshow("img",img);
        imshow("binary",binary);
        waitKey(1);

    }
}

void lunkuoxinxi()
{
    //用四个点表示三角形轮廓
    vector<Point> contour;
    contour.push_back(Point2f(0,0));
    contour.push_back(Point2f(10,0));
    contour.push_back(Point2f(10,10));
    contour.push_back(Point2f(5,5));
    double area=contourArea(contour);//计算轮廓面积函数
    cout<<"area="<<area<<endl;

    double len0=arcLength(contour,true);//计算轮廓周长函数(轮廓点坐标，轮廓是否闭合标志)
    double len1=arcLength(contour,false);
    cout<<"len0="<<len0<<endl;
    cout<<"len1="<<len1<<endl;

    waitKey(0);

}

void lunkuowaijieduobianxing()
{
    Mat img,img1,img2,canny;
    VideoCapture cap(0);

    vector<vector<Point>> contours;//存放找到的轮廓
    vector<Vec4i> hie;

    int n,i;

    while(1)
    {
        cap.read(img);

        cvtColor(img,img,COLOR_BGR2GRAY);//将图像转为灰度图

        img.copyTo(img1);//深拷贝绘制最大外界矩形
        img.copyTo(img2);//深拷贝绘制最小外界矩形

        Canny(img,canny,80,160,3,false);//利用边缘检测二值化

        Mat kenrel=getStructuringElement(0,Size(3,3));
        dilate(canny,canny,kenrel);//膨胀运算

        findContours(canny,contours,hie,0,2,Point());//寻找轮廓


        //寻找外接矩形
        for(n=0;n<contours.size();n++)
        {
            //最大外界矩形
            Rect rect=boundingRect(contours[n]);//最大轮廓寻找函数(二维点集合)
            rectangle(img1,rect,Scalar(0,0,255),2,8,0);

            //最小外接矩形
            RotatedRect rrect=minAreaRect(contours[n]);//最小轮廓寻找函数(二维点集合)
            Point2f points[4];
            rrect.points(points);//读取最小外接矩形四个顶点
            Point2f cpt=rrect.center;//最小外接矩形中心

            //绘制旋转矩形与中心位置
            for(int i=0;i<4;i++)
            {
                if(i==3)
                {
                    line(img2,points[i],points[0],Scalar(0,255,0),2,8,0);
                    break;
                }
                line(img2,points[i],points[i+1],Scalar(0,255,0),2,8,0);
            }

            //绘制矩形的中心
            circle(img2,cpt,4,Scalar(255,0,0),-1,8,0);

        }
        imshow("img",img);
        imshow("max",img1);
        imshow("min",img2);
        imshow("canny",canny);
        waitKey(1);

    }
}